//
//  PopupView.swift
//  ShimaPlayer
//
//  Created by Miracolo Bosco on 2025/7/10.
//

import UIKit
import SnapKit

enum PopupStyle {
    case bottomSheet(height: CGFloat? = nil)  // 底部弹出，可指定高度
    case alert(width: CGFloat? = nil)        // 居中弹出，可指定宽度
    case custom(sourceView: UIView, size: CGSize) // 指定位置弹出
}

class PopupView<T: UIView>: UIView {
    
    // MARK: - Properties
    private let contentView: T
    private let style: PopupStyle
    private let backgroundView = UIView()
    private weak var presentingViewController: UIViewController?
    
    private var needsSetupMenuConstraints = false
    private var menuSourceView: UIView?
    private var menuSize: CGSize?
    
    // MARK: - Initialization
    init(contentView: T, style: PopupStyle) {
        self.contentView = contentView
        self.style = style
        super.init(frame: .zero)
        
        if case .custom(let sourceView, let size) = style {
            self.menuSourceView = sourceView
            self.menuSize = size
            self.needsSetupMenuConstraints = true
        }
        
        setupViews()
        setupGestures()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Setup
    private func setupViews() {
        // 背景视图
        backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        backgroundView.alpha = 0
        addSubview(backgroundView)
        backgroundView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        // 内容视图
        addSubview(contentView)
//        contentView.layer.cornerRadius = 12
        contentView.layer.masksToBounds = true
        
        // 根据样式设置约束
        switch style {
        case .bottomSheet(let height):
            setupBottomSheetConstraints(height: height)
        case .alert(let width):
            setupAlertConstraints(width: width)
        case .custom(let sourceView, let size):
            setupMenuConstraints(sourceView: sourceView, size: size)
        }
    }
    
    private func setupBottomSheetConstraints(height: CGFloat?) {
        contentView.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview()
            make.bottom.equalTo(self.snp.bottom).offset(contentView.bounds.height)
            
            if let height = height {
                make.height.equalTo(height)
            } else {
                make.height.equalTo(contentView.bounds.height)
            }
        }
    }
    
    private func setupAlertConstraints(width: CGFloat?) {
        contentView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            
            if let width = width {
                make.width.equalTo(width)
            } else {
                make.width.equalToSuperview().multipliedBy(0.8)
            }
        }
    }
    
    private func setupMenuConstraints(sourceView: UIView, size: CGSize, closure: ((_ make: ConstraintMaker) -> Void)? = nil) {
        // 确保 sourceView 已经被添加到视图层级中
        guard sourceView.superview != nil else {
            print("Warning: Source view is not in the view hierarchy")
            return
        }
        
        // 确保 self 已经被添加到视图层级中
        guard let superview = self.superview else {
            print("Warning: PopupView is not in the view hierarchy")
            return
        }
        
        if let closure {
            contentView.snp.remakeConstraints(closure)
        }

    }
    
    private func setupGestures() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleBackgroundTap))
        backgroundView.addGestureRecognizer(tapGesture)
    }
    
    // MARK: - Actions
    @objc private func handleBackgroundTap() {
        dismiss()
    }
    
    // MARK: - Presentation Methods
    func show(in viewController: UIViewController, constraints: ((_ make: ConstraintMaker) -> Void)? = nil) {
        presentingViewController = viewController
        
        // 添加到视图层级
        viewController.view.addSubview(self)
        self.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        // 延迟设置 menu 约束
        if needsSetupMenuConstraints,
           let sourceView = menuSourceView,
           let size = menuSize{
            setupMenuConstraints(sourceView: sourceView, size: size, closure: constraints)
            needsSetupMenuConstraints = false
        }
        
        if let constraints {
            contentView.snp.remakeConstraints(constraints)
        }
        
        // 根据样式执行不同的动画
        switch style {
        case .bottomSheet:
            animateBottomSheetPresentation()
        case .alert:
            animateAlertPresentation()
        case .custom:
            animateMenuPresentation()
        }
    }
    
    private func animateBottomSheetPresentation() {
        layoutIfNeeded()
        
        contentView.snp.updateConstraints { make in
            make.bottom.equalTo(self.snp.bottom)
        }
        
        UIView.animate(withDuration: 0.3) {
            self.backgroundView.alpha = 1
            self.layoutIfNeeded()
        }
    }
    
    private func animateAlertPresentation() {
        contentView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
        contentView.alpha = 0
        
        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [], animations: {
            self.backgroundView.alpha = 1
            self.contentView.transform = .identity
            self.contentView.alpha = 1
        }, completion: nil)
    }
    
    private func animateMenuPresentation() {
        contentView.alpha = 0
        contentView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
        
        UIView.animate(withDuration: 0.2) {
            self.backgroundView.alpha = 1
            self.contentView.alpha = 1
            self.contentView.transform = .identity
        }
    }
    
    func dismiss(completion: (() -> Void)? = nil) {
        switch style {
        case .bottomSheet:
            contentView.snp.updateConstraints { make in
                make.bottom.equalTo(self.snp.bottom).offset(contentView.bounds.height)
            }
            
            UIView.animate(withDuration: 0.3, animations: {
                self.backgroundView.alpha = 0
                self.layoutIfNeeded()
            }, completion: { _ in
                self.removeFromSuperview()
                completion?()
            })
            
        case .alert, .custom:
            UIView.animate(withDuration: 0.2, animations: {
                self.backgroundView.alpha = 0
                self.contentView.alpha = 0
                self.contentView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
            }, completion: { _ in
                self.removeFromSuperview()
                completion?()
            })
        }
    }
}
